/**
 * @param {number} numCourses
 * @param {number[][]} prerequisites
 * @return {boolean}
 */
var canFinish = function (numCourses, prerequisites) {
    let count = 0,
        preorderCourse = [],
        degree = new Array(numCourses).fill(0),
        relyMap = new Map();

    for (let i = 0; i < prerequisites.length; i++) {
        let item = prerequisites[i];
        // 维护每个节点的入度
        degree[item[0]]++
        // 维护所有节点的依赖关系
        if (relyMap.get(item[1])) {
            relyMap.get(item[1]).push(item[0])
        } else {
            relyMap.set(item[1], [item[0]])
        }
    }

    // 将目前入度为0的节点放入数组
    for (let i = 0; i < degree.length; i++) {
        if (degree[i] === 0) {
            preorderCourse.push(i)
        }
    }

    while (preorderCourse.length > 0) {
        // 课程能修的先修，item为能修的课程
        let item = preorderCourse.pop(),
            relyArr = relyMap.get(item) || [];
        count++;
        for (let index of relyArr) {
            // 如果节点的入度为0，证明可以修
            if (--degree[index] === 0) {
                preorderCourse.push(index)
            }
        }
    }

    return count === numCourses;
};